
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#include "av_streamer.h"
#include "dmai_fifo.h"
#include "dmai_buffer.h"

#define AVS_PORT		9998
#define MAX_AVS_STREAMER	4

static int avs = -1;
static int avs_socket[MAX_AVS_STREAMER];

extern int forceHeader;
extern HANDLE av_data_in, av_data_out;

void
av_streamer_send (char *data, int length)
{
	int i, ret;

	for (i=0; i<MAX_AVS_STREAMER; i++) {
		if (avs_socket[i] > 0) {
			ret = send (avs_socket[i], data, length, 0);
			if (ret <= 0) {
				close (avs_socket[i]);
				avs_socket[i] = -1;
			}
		}
	}
}

static void
av_streamer_thread (void)
{
	fd_set rfds;
	struct timeval tv;
	struct sockaddr_in addr;
	socklen_t addrlen = sizeof (struct sockaddr_in);
	HANDLE data;
	int s, i;

	while (1) {
		FD_ZERO (&rfds);
		FD_SET (avs, &rfds);
		tv.tv_sec = 0;
		tv.tv_usec = 20000;
		select (avs+1, &rfds, NULL, NULL, &tv);
		if (FD_ISSET (avs, &rfds)) {
			s = accept(avs, (struct sockaddr *)&addr, &addrlen);
			if (s > 0) {
				for (i=0; i<MAX_AVS_STREAMER; i++) {
					if (avs_socket[i] == -1)
						break;
				}
				if (i >= MAX_AVS_STREAMER)
					close (s);
				else {
					avs_socket[i] = s;
					forceHeader = 1;
				}
			}
		}
		if (fifo_getNumEntries(av_data_out) > 0 && !fifo_get (av_data_out, &data)) {
			av_streamer_send (buffer_getUserPtr(data), buffer_getNumBytesUsed(data));
			fifo_put (av_data_in, data);
		}
	}
}

int
av_streamer_init (void)
{
	struct sockaddr_in addr;
	pthread_t pid;
	int val = 1, i;

	for (i=0; i<MAX_AVS_STREAMER; i++)
		avs_socket[i] = -1;

	if ((avs = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		printf ("avs socket() error!\r\n");
		return -1;
	}
	if (setsockopt (avs, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof (val)) != 0) {
		printf ("avs setsockopt() error!\n");
		return -1;
	}
	addr.sin_family = AF_INET;
	addr.sin_port = htons(AVS_PORT);
	addr.sin_addr.s_addr = INADDR_ANY;

	if (bind(avs, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
		printf ("avs bind() error!\r\n");
		return -1;
	}
	if (listen(avs, 5) == -1) {
		printf ("avs listen() error!\r\n");
		return -1;
	}

	if (pthread_create (&pid, NULL, (void *)av_streamer_thread, NULL) != 0) {
		printf ("pthread_create av_streamer_thread error!\n");
		return -1;
	}

	return 0;
}
